﻿using System;
using Common;
using DomainModel;
using DomainModel.Entities;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NHibernate.Collection.Generic;
using NHibernate.Criterion;
using Remotion.Linq.Collections;
using System.Collections.Generic;

namespace DomainModel.UnitTesting
{
    [TestClass]
    public class SessionTests : DomainModelTestBase
    {
        [TestMethod]
        public void CanGetSession()
        {
            var session = SessionProvider.NewSession;
            Assert.IsNotNull(session);
            Assert.IsTrue(session.IsOpen);
        }

        [TestMethod]
        public void NewSessionGivesDifferentSessionEveryTime()
        {
            var session = SessionProvider.NewSession;
            Assert.IsNotNull(session);
            var session2 = SessionProvider.NewSession;
            Assert.IsNotNull(session2);
            Assert.AreNotEqual(session, session2);
        }

        [TestMethod]
        public void CanAddUserAndStatusAtOnce()
        {
            InDbSession(session =>
                            {
                                var statusInfo = ObjectMother.StatusInfo.PrepareStatusInfo();
                                var user = ObjectMother.User.PrepareUser(statusInfo);
                                session.Save(user);
                                session.Flush();

                                var userFromDb = session.Get<User>(user.UserId);
                                Assert.IsNotNull(userFromDb);
                                Assert.AreEqual(user.StatusInfo, userFromDb.StatusInfo);
                            });
        }

        [TestMethod]
        public void CanAddTwoUsersAndUndeliveredMessage()
        {
            InDbSession(session =>
            {
                var statusInfo = ObjectMother.StatusInfo.PrepareStatusInfo();
                var user = ObjectMother.User.PrepareUser(statusInfo);
                session.Save(user);
                var user2 = ObjectMother.User.PrepareUser(statusInfo);
                session.Save(user2);
                session.Flush();

                var userFromDb = session.Get<User>(user.UserId);
                Assert.IsNotNull(userFromDb);
                Assert.AreEqual(user.StatusInfo, userFromDb.StatusInfo);

                var message = new UndeliveredMessage() {FromUser=user,ToUser = user2, DateSent = DateTime.Now};
                //user.MyUndeliveredMessages.Add(message);

                session.Save(message);
                session.Flush();
                session.Clear();
                session.Refresh(user);
                //var user3 = session.Get<User>(user.UserId);
                //var user4 = session.Get<User>(user2.UserId);
                Assert.AreEqual(1,user.MyUndeliveredMessages);
                Assert.AreEqual(0,user.UndeliveredMessagesToMe);


            });
        }


        [TestMethod]
        public void CanAddTwoUsersAndSetThemAsFriends()
        {
            InDbSession(session =>
            {
                var statusInfo = ObjectMother.StatusInfo.PrepareStatusInfo();
                var user = ObjectMother.User.PrepareUser(statusInfo);
                session.Save(user);
                var user2 = ObjectMother.User.PrepareUser(statusInfo);
                session.Save(user2);
                session.Flush();               

            //user.Friends=new ObservableCollection<User>();
                
                user.Friends.Add(user2);
                user2.Friends.Add(user);
                session.Flush();


                var userFromDb = session.Get<User>(user.UserId);
                Assert.IsNotNull(userFromDb);
                Assert.AreEqual(user.StatusInfo, userFromDb.StatusInfo);

                Assert.AreEqual(1, userFromDb.Friends.Count);
                Assert.AreEqual(1,user2.Friends.Count);


            });
        }

        [TestMethod]
        public void AddUserFlushAndRollbackLeavesStateOfTableUntouched()
        {
            int usersCountBefore = 0;

            InDbSession(session =>
                            {
                                usersCountBefore =
                                    session.CreateCriteria<User>().SetProjection(Projections.RowCount()).
                                        UniqueResult<int>();
                                var statusInfo = ObjectMother.StatusInfo.PrepareStatusInfo();
                                var user = ObjectMother.User.PrepareUser(statusInfo);
                                session.Save(user);
                                session.Flush();

                                var userFromDb = session.Get<User>(user.UserId);
                                Assert.IsNotNull(userFromDb);
                                Assert.AreEqual(user.StatusInfo, userFromDb.StatusInfo);
                            });

            InDbSession(session =>
                            {
                                int usersCountAfter =
                                    session.CreateCriteria<User>().SetProjection(Projections.RowCount()).
                                        UniqueResult<int>();
                                Assert.AreEqual(usersCountBefore, usersCountAfter);
                            });
        }



    }
}

